﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Reflection;
using System.ComponentModel;
using System.Xml.Linq;

namespace devtm.Editor.TypeSelector.AttributeBuilder
{

    

    public class Constructor : TreeViewItem, INotifyPropertyChanged
    {

        private System.Reflection.ConstructorInfo item;

        public Constructor(AttributeMap attributeMap, System.Reflection.ConstructorInfo item)
        {
            AttributeMap = attributeMap;
            this.item = item;

            CreateListeExclude();

            bool m = item.GetParameters().Count() != 0 || attributeMap.AttributeSelected.GetProperties().Count() !=0 ;
            if (m)
                AddParameter(false);

            foreach (ParameterInfo parameter in item.GetParameters())
                AddParameter(parameter);

            if (m)
                AddParameter(true);

            BuildTitle();

            this.Expanded += new System.Windows.RoutedEventHandler(Constructor_Expanded);
        }


        private void BuildTitle()
        {
            StringBuilder s = new StringBuilder();
            bool e = false;

            s.Append(item.ReflectedType.Name + " (");

            foreach (ParameterInfo parameter in item.GetParameters())
            {
                if (e)
                    s.Append(", ");

                s.Append(parameter.ParameterType.Name + " " + parameter.Name);

                e = true;

            }

            s.Append(")");
            Title = s.ToString();
            ConstructorUserControl h = new ConstructorUserControl();
            h.Constructor = this;
            h.Txt.Content = Title;
            Header = h;

        }

        //public bool IsChecked 
        //{
        //    get { return (bool)(this.Header as ConstructorUserControl).radioButton1.IsChecked; } 
        //    set { (this.Header as ConstructorUserControl).radioButton1.IsChecked = value; } 
        
        //}

        public string Title { get; private set; }
        public AttributeMap AttributeMap { get; set; }

        #region INotifyPropertyChanged

        protected void MyPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, e);
        }

        protected void MyPropertyChanged(string propertyName)
        {
            MyPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public List<PropertyInfo> GetAvailbleProperty()
        {

            List<string> lst = new List<string>();
            foreach (Parameter item in this.Items)
                if (!string.IsNullOrEmpty (item.Name))
                    lst.Add(item.Name.ToLower());

            List<PropertyInfo> l = new List<PropertyInfo>();

            foreach (PropertyInfo property in AttributeMap.AttributeSelected.GetProperties())
                if (!lst.Contains(property.Name.ToLower()) && property.Name != "TypeId" && property.Name != "ValidatorInstance" && !ExludeList.Contains(property.Name))
                {
                    if (property.PropertyType == typeof(string) || property.PropertyType == typeof(Type) || property.PropertyType.IsEnum || property.PropertyType.IsPrimitive)
                        l.Add(property);
                    else 
                    {

                    }
                }

            return l;
        }


        private List<String> ExludeList = new List<string>();
        private void CreateListeExclude()
        {

            Object _instanceTest = null;

            try
            {

                List<Object> obj = new List<object>();

                foreach (ParameterInfo parameter in item.GetParameters())
                    obj.Add(GetParameter(parameter.ParameterType));

                _instanceTest = Activator.CreateInstance(AttributeMap.AttributeSelected, obj.ToArray());

                foreach (PropertyInfo prop in AttributeMap.AttributeSelected.GetProperties())
                {

                    var value = prop.GetValue(_instanceTest, null);

                    foreach (var tem in obj)
                        if (value != null && tem.GetType() == value.GetType() && tem == value)
                            ExludeList.Add(prop.Name);

                }

            }

            catch (Exception ex)
            {


                var e = ex;
                ExludeList = new List<string>();

            }

        }

        private static object GetParameter(Type ParameterType)
        {

            if (ParameterType == typeof(string))
            {
                return "MyTest";
            }
            else if (ParameterType == typeof(DateTime))
            {
                return DateTime.Now;
            }
            else if (ParameterType == typeof(TimeSpan))
            {
                return new TimeSpan(56985658);
            }
            else if (ParameterType == typeof(Type))
            {
                return typeof(System.BitConverter);
            }
            else if (ParameterType.IsEnum)
            {
                var i = Enum.GetValues(ParameterType);
                return i.GetValue(i.Length - 1); 
            }
            else if (ParameterType.IsPrimitive)
            {
                if (ParameterType == typeof(byte))
                    return (byte)100;
                else
                    return 100;
            }
            else
            {
                return null;
            }
        }

        private Parameter AddParameter(ParameterInfo parameter)
        {
            Parameter p = new Parameter(this, parameter);
            this.Items.Add(p);
            return p;
        }

        public Parameter AddProperty(PropertyInfo property)
        {
            Parameter p = new Parameter(this, property);
            this.Items.Insert(this.Items.Count -1, p);
            return p;
        }

        private Parameter AddParameter(PropertyInfo property)
        {
            Parameter p = new Parameter(this, property);
            this.Items.Add(p);
            if (_last != null)
                (_last.Header as TitleChoosePropertyLastUserControl).RefreshAdd();

            return p;
        }

        private void RefreshAdd()
        {

            if (_last != null)
                _last.RefreshAdd();

        }

        private Parameter _last;
        private void AddParameter(bool last)
        {

            Parameter _lst = new Parameter(this);
            this.Items.Add(_lst);

            if (last)
            {
                _last = _lst;
            }

        }


        internal void RefreshLost(object e)
        {
            foreach (Parameter item in this.Items)
                item.Lost(e);
            

        }

        void Constructor_Expanded(object sender, System.Windows.RoutedEventArgs e)
        {
            AttributeMap.ConstructorChecked(this);
        }


        internal XElement Serialize()
        {

            XElement ret = new XElement("ctr", new XAttribute("sgn", Title));
            
            foreach (Parameter item in this.Items)
            {
                XElement e = item.Serialize();
                if (e != null)
                    ret.Add(e);
            }

            return ret;
        }

        internal void UnSerialize(XElement node)
        {
            foreach (XElement nde in node.Elements())
            {
                string nodeName = (string)nde.Name.LocalName;
                foreach (Parameter parameter in this.Items)
                {

                    if (parameter.Name == nodeName)
                    {
                        parameter.UnSerialize(nde);
                        return;
                    }

                }

                foreach (PropertyInfo item in AttributeMap.AttributeSelected.GetProperties())
	            {
                    if (item.Name == nodeName)
                    {
                        Parameter p = AddProperty(item);
                        p.UnSerialize(nde);
                        return;
                    }

                }

                //PropertyInfo property = AttributeMap.AttributeSelected.GetProperties()

                //AddProperty(PropertyInfo property)
            }
        }

    }
}
